/*
 * @Author: your name
 * @Description: 
 * @FilePath: /code/test.cpp
 */

#include <iostream>
#include <thread>
#include <experimental/coroutine>
#include <chrono>
#include <functional>

#include <unistd.h>
// clang++ -std=c++2a -fcoroutines-ts -lstdc++ co_vs_callback.cpp

void testtime(std::function<void()> f)
{
    using namespace std::literals;
    const std::chrono::time_point<std::chrono::steady_clock> start =
        std::chrono::steady_clock::now();
 
    f();
 
    const std::chrono::time_point<std::chrono::steady_clock> end = std::chrono::steady_clock::now();
 
        std::cout
      <<"Function: "
      <<__FUNCTION__ 
      <<" took "
      << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << "µs ≈ "
      << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()<< "ms ≈ " 
      << (end - start) / 1s << "s.\n";
      //enables the usage of 24h, 1ms, 1s instead of // e.g. std::chrono::hours(24), accordingly
}


using call_back = std::function<void(int)>;
void Add100ByCallback(int init, call_back f) // 异步调用
{
	std::thread t([init, f]() {
		std::this_thread::sleep_for(std::chrono::seconds(5));
		f(init + 100);
	});
	t.detach();
}

struct Add100AWaitable
{
	Add100AWaitable(int init):init_(init) {}
	bool await_ready() const { return false; }
	int await_resume() { return result_; }
	void await_suspend(std::experimental::coroutine_handle<> handle)
	{
		auto f = [handle, this](int value) mutable {
			result_ = value;
			handle.resume();
		};
		Add100ByCallback(init_, f); // 调用原来的异步调用
	}
	int init_;
	int result_;
};

struct Task
{
	struct promise_type {
		auto get_return_object() { return Task{}; }
		auto initial_suspend() { return std::experimental::suspend_never{}; }
		auto final_suspend() noexcept { return std::experimental::suspend_never{}; }
		void unhandled_exception() { std::terminate(); }
		void return_void() {}
	};
};


//协程的优点是可以用同步的处理方式实现异步回调的性能
Task Add100ByCoroutine(int init, call_back f)
{
	int ret = co_await Add100AWaitable(init);
	ret = co_await Add100AWaitable(ret);
	ret = co_await Add100AWaitable(ret);
    //一行用了5s
	f(ret);
}

void test()
{
    for(int i=0;i<2000;i++)
    Add100ByCallback(5, [](int value){ std::cout<<"get result: "<<value<<"\n"; });
    
    /*
	Add100ByCoroutine(10, [](int value){ std::cout<<"get result from coroutine1: "<<value<<"\n"; });
	Add100ByCoroutine(20, [](int value){ std::cout<<"get result from coroutine2: "<<value<<"\n"; });
	Add100ByCoroutine(30, [](int value){ std::cout<<"get result from coroutine3: "<<value<<"\n"; });
	Add100ByCoroutine(40, [](int value){ std::cout<<"get result from coroutine4: "<<value<<"\n"; });
    */
    getchar();
}

int main()
{
	testtime(test);
    return 0;
}


//这 异步就是屌啊 ，这八核就是棒啊！
/*
using call_back = std::function<void(int)>;
void Add100ByCallback(int init, call_back f) //init是传入的初始值，add之后的结果由回调函数f通知
{
    std::thread t([init, f]() {
        std::this_thread::sleep_for(std::chrono::seconds(5)); // sleep一下，假装很耗时
        f(init + 100); // 耗时的计算完成了，调用回调函数
    });
    t.detach();
}
int main()
{
    for(int i=0;i<100000;i++)
        std::cout<<i<<std::endl;
    Add100ByCallback(5, [](int value){ std::cout<<"get result: "<< value <<"\n"; });
    for(int i=100000;i>0;i--)
        std::cout<<i<<std::endl;
    sleep(5);
    return 0;
}*/